package com.sptpc.learnspring.security;

import cn.hutool.json.JSONUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.sptpc.learnspring.controller.request.LoginUserRequest;
import com.sptpc.learnspring.global.response.BusinessStatusCode;
import com.sptpc.learnspring.global.response.GlobalResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Collection;

/**
 * 认证
 */
@Slf4j
public class JWTAuthenticationFilter
        extends UsernamePasswordAuthenticationFilter {
    private AuthenticationManager authManager;

    public JWTAuthenticationFilter(AuthenticationManager authenticationManager) {
        this.authManager = authenticationManager;
        // 修改登录api的url
        // 默认为/login
        super.setFilterProcessesUrl("/user/login");
    }

    // 从请求中获得用户名和密码进行认证
    @Override
    public Authentication attemptAuthentication(
            HttpServletRequest request, HttpServletResponse response)
            throws AuthenticationException {
        LoginUserRequest user = null;
        try {
            user = new ObjectMapper().readValue(request.getInputStream(),
                    LoginUserRequest.class);
            return authManager.authenticate(
                    new UsernamePasswordAuthenticationToken(
                            user.getUsername(), user.getPassword()));
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }

    // 认证成功
    @Override
    protected void successfulAuthentication(
            HttpServletRequest request, HttpServletResponse response,
            FilterChain chain, Authentication authResult)
            throws IOException, ServletException {
        JwtUser jwtUser = (JwtUser) authResult.getPrincipal();

        String role = "";
        Collection<? extends GrantedAuthority> authorities = jwtUser.getAuthorities();
        for (GrantedAuthority authority : authorities) {
            role = authority.getAuthority();
        }
        String token = JwtUtil.createJWT(jwtUser.getUsername(), role);
        log.info("认证成功:{}", token);
        // 构建完整的token，按jwt格式为：Bearer token
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json; charset=utf-8");
        // token写到http header中
        response.setHeader("token", "Bearer " + token);
        // 并返回操作成功信息
        GlobalResponse result = GlobalResponse.success();
        response.getWriter().write(JSONUtil.toJsonStr(result));
    }

    // 认证失败
    @Override
    protected void unsuccessfulAuthentication(
            HttpServletRequest request, HttpServletResponse response,
            AuthenticationException failed) throws IOException, ServletException {
        log.warn("认证失败");
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json; charset=utf-8");
        GlobalResponse result = GlobalResponse.fail(BusinessStatusCode.AUTHEN_FAIL);
        response.getWriter().write(JSONUtil.toJsonStr(result));
    }
}
